#include <iostream>
#include <event2/event.h>
#include <event2/listener.h>
#include  <event2/bufferevent.h>
#include <string.h>
#ifndef _WIN32
#include <signal.h>
#endif
using namespace std;

void read_cb(struct bufferevent *bev, void *ctx){
        cout<<"[read]"<<endl;
        //读取输入缓冲数据
        char data[1024] = {0};
        int len = bufferevent_read(bev,  data, sizeof(data)-1);
        cout<<"["<<data<<"]"<<endl;
        if(len <= 0){
                return;
        }
        if(strstr(data, "quit") != NULL){
                cout<<"quit"<<endl;;
                //退出 并关闭客户端sock
                bufferevent_free(bev);
        }
        //发送数据 写入到输出缓冲
        bufferevent_write(bev, "ok",  3);
}
//正常的连接三次握手 和 断开四次挥手是可以进来的
void write_cb(struct bufferevent *bev, void *ctx){
        cout<<"[write]"<<endl;
}
//异常 超时 错误 (连接断开)等 会进入 
void event_cb(struct bufferevent *bev, short what, void *ctx){
        cout<<"[event]"<<endl;
        //读取超时事件发生后，数据读取停止
        if(what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING){
                cout<<"BEV_EVENT_READING  BEV_EVENT_TIMEOUT"<<endl;
                //bufferevent_enable(bev, EV_READ);//重新让他可读
                bufferevent_free(bev);
        }else if(what & BEV_EVENT_ERROR){
                 bufferevent_free(bev);
        }else{
                cout<<"OTHRES"<<endl;
        }
}

void listener_cb(struct evconnlistener *ev, evutil_socket_t lfd,
                                         struct sockaddr *sin, int socklen, void *arg){
        sockaddr_in *csin = (sockaddr_in *)sin;
        char ip[16] = {0};
        evutil_inet_ntop(sin->sa_family,  &csin->sin_addr, ip, sizeof(ip)-1);
        cout<<"client ip is "<<ip<<" port is "<<ntohs(csin->sin_port)<<endl;

        event_base *base = (event_base *)arg;
        //创建bufferevent上下文  BEV_OPT_CLOSE_ON_FREE 清理bufferevent时关闭socket
        bufferevent *bev = bufferevent_socket_new(base, lfd, BEV_OPT_CLOSE_ON_FREE);
        
        //添加监听事件
        bufferevent_enable(bev, EV_READ|EV_WRITE);

        //设置水位
        //读取水位
        bufferevent_setwatermark(bev, EV_READ,
                        5,         //低水位 0就是无限制 默认是0 
                        10        //高水位 0就是无限制  默认是0 
                        );
        //写水位
        bufferevent_setwatermark(bev, EV_WRITE,
                        5,        //低水位 0就是无限制 默认是0   缓冲区数据低于5 写入回调被调用
                        0         // 高水位无效
                        );
        
        //超时时间的设置
        timeval t1 = {3, 0};
        bufferevent_set_timeouts(bev, &t1, 0);

        //设置回调函数
        bufferevent_setcb(bev, read_cb, write_cb, event_cb, base);
}

int main(int argc, char const *argv[]){
#ifdef _WIN32
        //初始化socket库
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
#else
        //忽略管道信号 发送数据给已关闭的socket
        if(signal(SIGPIPE,SIG_IGN) == SIG_IGN){
                return 1;
        }
#endif
        event_base *base = event_base_new();

        //创建网络服务器
        sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(8080);

        evconnlistener *ev = evconnlistener_new_bind(base, 
                                        listener_cb, base,
                                        LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
                                        -1, //listen block
                                        (sockaddr *)&sin, sizeof(sin));

        event_base_dispatch(base);

        evconnlistener_free(ev);

        event_base_free(base);

        return 0;
}